package com.codeplatform.controller;

import com.codeplatform.common.Result;
import com.codeplatform.dto.*;
import com.codeplatform.entity.User;
import com.codeplatform.service.AuthService;
import com.codeplatform.service.CodeRecordService;
import com.codeplatform.util.ColorLogger;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户认证控制器
 */
@Api(tags = "用户认证管理")
@Slf4j
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
@Validated
public class AuthController {
    
    private final AuthService authService;
    private final CodeRecordService codeRecordService;
    
    /**
     * 用户注册
     */
    @ApiOperation(value = "用户注册", notes = "新用户注册账号")
    @PostMapping("/register")
    public Result<AuthResponse> register(@ApiParam(value = "注册请求信息", required = true) @Valid @RequestBody RegisterRequest request) {
        try {
            ColorLogger.business("用户注册", "用户名: %s, 邮箱: %s", request.getUsername(), request.getEmail());
            AuthResponse response = authService.register(request);
            ColorLogger.success("用户注册成功: %s", request.getUsername());
            return Result.success(response, "注册成功");
        } catch (Exception e) {
            ColorLogger.error("用户注册失败: %s", e, request.getUsername());
            return Result.error(e.getMessage());
        }
    }
    
    /**
     * 用户登录
     */
    @ApiOperation(value = "用户登录", notes = "用户登录获取访问令牌")
    @PostMapping("/login")
    public Result<AuthResponse> login(@ApiParam(value = "登录请求信息", required = true) @Valid @RequestBody LoginRequest request) {
        try {
            ColorLogger.business("用户登录", "用户名: %s", request.getUsernameOrEmail());
            AuthResponse response = authService.login(request);
            ColorLogger.success("用户登录成功: %s", request.getUsernameOrEmail());
            ColorLogger.security("用户登录", request.getUsernameOrEmail(), "登录成功");
            return Result.success(response, "登录成功");
        } catch (Exception e) {
            ColorLogger.error("用户登录失败: %s", e, request.getUsernameOrEmail());
            ColorLogger.security("登录失败", request.getUsernameOrEmail(), e.getMessage());
            return Result.error(e.getMessage());
        }
    }
    
    /**
     * 刷新令牌
     */
    @ApiOperation(value = "刷新访问令牌", notes = "使用刷新令牌获取新的访问令牌")
    @PostMapping("/refresh")
    public Result<AuthResponse> refreshToken(@ApiParam(value = "刷新令牌请求", required = true) @Valid @RequestBody RefreshTokenRequest request) {
        try {
            AuthResponse response = authService.refreshToken(request);
            return Result.success(response, "令牌刷新成功");
        } catch (Exception e) {
            log.error("令牌刷新失败", e);
            return Result.error(e.getMessage());
        }
    }
    
    /**
     * 用户登出
     */
    @ApiOperation(value = "用户登出", notes = "用户登出并使令牌失效")
    @PostMapping("/logout")
    public Result<Void> logout(HttpServletRequest request) {
        try {
            String token = extractTokenFromRequest(request);
            if (token == null) {
                return Result.error("未找到访问令牌");
            }
            
            Boolean success = authService.logout(token);
            if (success) {
                return Result.success(null, "登出成功");
            } else {
                return Result.error("登出失败");
            }
        } catch (Exception e) {
            log.error("用户登出失败", e);
            return Result.error("登出失败");
        }
    }
    
    /**
     * 验证令牌
     */
    @ApiOperation(value = "验证访问令牌", notes = "验证访问令牌是否有效")
    @GetMapping("/validate")
    public Result<Map<String, Object>> validateToken(HttpServletRequest request) {
        try {
            String token = extractTokenFromRequest(request);
            if (token == null) {
                return Result.unauthorized("未找到访问令牌");
            }
            
            User user = authService.validateToken(token);
            if (user == null) {
                return Result.unauthorized("令牌无效或已过期");
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("valid", true);
            result.put("userId", user.getId());
            result.put("username", user.getUsername());
            
            return Result.success(result, "令牌验证成功");
        } catch (Exception e) {
            log.error("令牌验证失败", e);
            return Result.unauthorized("令牌验证失败");
        }
    }
    
    /**
     * 获取当前用户信息
     */
    @ApiOperation(value = "获取当前用户信息", notes = "根据令牌获取当前登录用户的详细信息")
    @GetMapping("/me")
    public Result<AuthResponse.UserInfo> getCurrentUser(HttpServletRequest request) {
        try {
            String token = extractTokenFromRequest(request);
            if (token == null) {
                return Result.unauthorized("未找到访问令牌");
            }
            
            User user = authService.validateToken(token);
            if (user == null) {
                return Result.unauthorized("令牌无效或已过期");
            }
            
            AuthResponse.UserInfo userInfo = AuthResponse.UserInfo.builder()
                    .id(user.getId())
                    .username(user.getUsername())
                    .nickname(user.getNickname())
                    .email(user.getEmail())
                    .avatar(user.getAvatar())
                    .role(user.getRole())
                    .status(user.getStatus().toString())
                    .emailVerified(user.getEmailVerified())
    
                    .createdAt(user.getCreatedAt())
                    .lastLoginAt(user.getLastLoginAt())
                    .build();
            
            return Result.success(userInfo, "获取用户信息成功");
        } catch (Exception e) {
            log.error("获取用户信息失败", e);
            return Result.error("获取用户信息失败");
        }
    }
    
    /**
     * 检查用户名是否可用
     */
    @ApiOperation(value = "检查用户名可用性", notes = "检查指定用户名是否已被注册")
    @GetMapping("/check-username")
    public Result<Map<String, Boolean>> checkUsername(
            @ApiParam(value = "要检查的用户名", required = true) @RequestParam @NotBlank(message = "用户名不能为空") String username) {
        try {
            Boolean available = authService.isUsernameAvailable(username);
            Map<String, Boolean> result = new HashMap<>();
            result.put("available", available);
            return Result.success(result, available ? "用户名可用" : "用户名已存在");
        } catch (Exception e) {
            log.error("检查用户名可用性失败", e);
            return Result.error("检查用户名可用性失败");
        }
    }
    
    /**
     * 检查邮箱是否可用
     */
    @ApiOperation(value = "检查邮箱可用性", notes = "检查指定邮箱是否已被注册")
    @GetMapping("/check-email")
    public Result<Map<String, Boolean>> checkEmail(
            @ApiParam(value = "要检查的邮箱地址", required = true) @RequestParam @Email(message = "邮箱格式不正确") String email) {
        try {
            Boolean available = authService.isEmailAvailable(email);
            Map<String, Boolean> result = new HashMap<>();
            result.put("available", available);
            return Result.success(result, available ? "邮箱可用" : "邮箱已被注册");
        } catch (Exception e) {
            log.error("检查邮箱可用性失败", e);
            return Result.error("检查邮箱可用性失败");
        }
    }
    

    
    /**
     * 修改密码
     */
    @ApiOperation(value = "修改密码", notes = "用户修改登录密码")
    @PostMapping("/change-password")
    public Result<Void> changePassword(
            @ApiParam(value = "修改密码请求", required = true) @RequestBody @Valid ChangePasswordRequest request,
            HttpServletRequest httpRequest) {
        try {
            String token = extractTokenFromRequest(httpRequest);
            if (token == null) {
                return Result.unauthorized("未找到访问令牌");
            }
            
            User user = authService.validateToken(token);
            if (user == null) {
                return Result.unauthorized("令牌无效或已过期");
            }
            
            Boolean success = authService.changePassword(
                user.getId(), request.getOldPassword(), request.getNewPassword());
            
            if (success) {
                return Result.success(null, "密码修改成功，请重新登录");
            } else {
                return Result.error("密码修改失败");
            }
        } catch (Exception e) {
            log.error("修改密码失败", e);
            return Result.error("密码修改失败: " + e.getMessage());
        }
    }
    
    /**
     * 重置密码
     */
    @ApiOperation(value = "重置密码", notes = "通过邮箱重置用户密码")
    @PostMapping("/reset-password")
    public Result<Void> resetPassword(
            @ApiParam(value = "用户邮箱地址", required = true) @RequestParam @Email(message = "邮箱格式不正确") String email) {
        try {
            Boolean success = authService.resetPassword(email);
            if (success) {
                return Result.success(null, "密码重置邮件已发送");
            } else {
                return Result.error("密码重置失败");
            }
        } catch (Exception e) {
            log.error("重置密码失败", e);
            return Result.error("密码重置失败");
        }
    }
    
    /**
     * 激活账户
     */
    @ApiOperation(value = "激活账户", notes = "通过激活令牌激活用户账户")
    @PostMapping("/activate")
    public Result<Void> activateAccount(@ApiParam(value = "激活令牌", required = true) @RequestParam String token) {
        try {
            Boolean success = authService.activateAccount(token);
            if (success) {
                return Result.success(null, "账户激活成功");
            } else {
                return Result.error("账户激活失败");
            }
        } catch (Exception e) {
            log.error("激活账户失败", e);
            return Result.error("账户激活失败");
        }
    }
    
    /**
     * 更新用户信息
     */
    @ApiOperation(value = "更新用户信息", notes = "更新当前登录用户的基本信息，可选择同时修改密码")
    @PutMapping("/me")
    public Result<AuthResponse.UserInfo> updateUserInfo(
            @ApiParam(value = "更新用户信息请求", required = true) @Valid @RequestBody UpdateUserInfoRequest request,
            HttpServletRequest httpRequest) {
        try {
            String token = extractTokenFromRequest(httpRequest);
            if (token == null) {
                return Result.unauthorized("未找到访问令牌");
            }
            
            User user = authService.validateToken(token);
            if (user == null) {
                return Result.unauthorized("令牌无效或已过期");
            }
            
            // 如果需要修改密码，进行密码验证
            if (request.shouldChangePassword()) {
                if (!request.isPasswordMatch()) {
                    return Result.error("两次输入的密码不一致");
                }
                if (request.getNewPassword().length() < 6) {
                    return Result.error("密码长度至少6个字符");
                }
            }
            
            AuthResponse.UserInfo updatedUserInfo = authService.updateUserInfo(
                user.getId(), request.getUsername(), request.getNickname(), request.getEmail(), 
                request.shouldChangePassword() ? request.getNewPassword() : null);
            
            return Result.success(updatedUserInfo, "用户信息更新成功");
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            return Result.error("更新用户信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取当前用户统计信息
     */
    @ApiOperation(value = "获取当前用户统计信息", notes = "获取当前登录用户的代码记录统计数据")
    @GetMapping("/stats")
    public Result<CodeRecordService.UserCodeStatistics> getCurrentUserStats(HttpServletRequest request) {
        try {
            String token = extractTokenFromRequest(request);
            if (token == null) {
                return Result.error("未提供访问令牌");
            }
            
            // 验证令牌并获取用户信息
            User user = authService.validateToken(token);
            if (user == null) {
                return Result.error("无效的访问令牌");
            }
            
            // 获取用户统计信息
            CodeRecordService.UserCodeStatistics statistics = codeRecordService.getUserStatistics(user.getId());
            return Result.success(statistics, "获取用户统计信息成功");
        } catch (Exception e) {
            log.error("获取用户统计信息失败", e);
            return Result.error("获取统计信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 从请求中提取令牌
     */
    private String extractTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
    

    
    /**
     * 更新用户信息请求DTO
     */
    public static class UpdateUserInfoRequest {
        @NotBlank(message = "用户名不能为空")
        private String username;
        
        private String nickname;
        
        @NotBlank(message = "邮箱不能为空")
        @Email(message = "邮箱格式不正确")
        private String email;
        
        // 可选的密码字段
        private String newPassword;
        
        private String confirmPassword;
        
        // getters and setters
        public String getUsername() {
            return username;
        }
        
        public void setUsername(String username) {
            this.username = username;
        }
        
        public String getNickname() {
            return nickname;
        }
        
        public void setNickname(String nickname) {
            this.nickname = nickname;
        }
        
        public String getEmail() {
            return email;
        }
        
        public void setEmail(String email) {
            this.email = email;
        }
        
        public String getNewPassword() {
            return newPassword;
        }
        
        public void setNewPassword(String newPassword) {
            this.newPassword = newPassword;
        }
        
        public String getConfirmPassword() {
            return confirmPassword;
        }
        
        public void setConfirmPassword(String confirmPassword) {
            this.confirmPassword = confirmPassword;
        }
        
        /**
         * 检查是否需要修改密码
         */
        public boolean shouldChangePassword() {
            return newPassword != null && !newPassword.trim().isEmpty();
        }
        
        /**
         * 检查密码是否匹配
         */
        public boolean isPasswordMatch() {
            if (!shouldChangePassword()) {
                return true;
            }
            return newPassword != null && newPassword.equals(confirmPassword);
        }
    }
    
    /**
     * 修改密码请求DTO
     */
    public static class ChangePasswordRequest {
        @NotBlank(message = "原密码不能为空")
        private String oldPassword;
        
        @NotBlank(message = "新密码不能为空")
        private String newPassword;
        
        @NotBlank(message = "确认密码不能为空")
        private String confirmPassword;
        
        // getters and setters
        public String getOldPassword() {
            return oldPassword;
        }
        
        public void setOldPassword(String oldPassword) {
            this.oldPassword = oldPassword;
        }
        
        public String getNewPassword() {
            return newPassword;
        }
        
        public void setNewPassword(String newPassword) {
            this.newPassword = newPassword;
        }
        
        public String getConfirmPassword() {
            return confirmPassword;
        }
        
        public void setConfirmPassword(String confirmPassword) {
            this.confirmPassword = confirmPassword;
        }
        
        public boolean isPasswordMatch() {
            return newPassword != null && newPassword.equals(confirmPassword);
        }
    }
}